/*
 * User: user
 * Date: 08/12/2007
 * Time: 20:33:02
 */
package org.conann.configuration;

import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Sets;
import net.jcip.annotations.Immutable;
import org.conann.container.BeansRegistry;
import org.conann.exceptions.WebBeansConfigurationException;
import static org.conann.metadata.AnnotationType.deployment;

import javax.webbeans.deployment.Production;
import javax.webbeans.deployment.Standard;
import javax.webbeans.types.DeploymentType;
import java.lang.annotation.Annotation;
import java.util.*;

@Immutable
public class Configuration {

    private final Set<Class<?>> activeComponents = Sets.newConcurrentHashSet();
    //    private Collection<Class<? extends Annotation>> activeBindingTypes;
    private final Collection<Class<? extends Annotation>> enabledDeploymentTypes;
    private final BeansRegistry beansRegistry;

    @SuppressWarnings({"ThisEscapedInObjectConstruction"})
    public Configuration(List<Class<? extends Annotation>> enabledDeploymentTypes) {
        this.enabledDeploymentTypes = createUnmodifiableLinkedHashSet(resolveEnabledDeploymentTypes(enabledDeploymentTypes));
        beansRegistry = new BeansRegistry(this);
    }

    public void addActiveComponent(Class<?> type) {
        checkNotNull(type);
        activeComponents.add(type);
    }

    private List<Class<? extends Annotation>> resolveEnabledDeploymentTypes(List<Class<? extends Annotation>> deploymentTypes) {
        checkNotNull(deploymentTypes);
        if (deploymentTypes.isEmpty()) {
            return Arrays.asList(Standard.class, Production.class);
        } else {
            if (!deploymentTypes.get(0).equals(Standard.class)) {
                throw new WebBeansConfigurationException("@%s component type must be specified as the first component type.\nPlease check your configuration.", Standard.class.getSimpleName());
            }
            for (Class<? extends Annotation> deploymentType : deploymentTypes) {
                if (!deployment.is(deploymentType)) {
                    throw new WebBeansConfigurationException("%s is not a valid deployment type (it is not annotated with @%s annotation).", deploymentType.getName(), DeploymentType.class.getSimpleName());
                }
            }
            return deploymentTypes;
        }
    }

    @SuppressWarnings({"unchecked"})
    private <T> Collection<T> createUnmodifiableLinkedHashSet(Collection<T> elements) {
        return Collections.unmodifiableCollection(new LinkedHashSet(elements));
    }

    public boolean isActiveComponent(Class<?> type) {
        checkNotNull(type);
        return activeComponents.contains(type);
    }

    Collection<Class<? extends Annotation>> getEnabledDeploymentTypes() {
        return enabledDeploymentTypes;
    }

    public BeansRegistry getBeansRegistry() {
        return beansRegistry;
    }
}